#! /usr/bin/perl
# -p = tipo de producto
# -s = id de sucursal
# -i = id de cliente
# -d = descripcion

# chequeo si se inicio el ambiente
if (! $ENV{"INICIART_INICIALIZADO"}){
	print "ERROR: ambiente no inicializado\n";
	exit(1);
}

if (defined($ENV{"MAEDIR"})){
	$MAEDIR = $ENV{"MAEDIR"};
}else{
	$MAEDIR = "mae/";
}

if (defined($ENV{"REPODIR"})){
	$REPODIR = $ENV{"REPODIR"};
}else{
	$REPODIR = "repodir/";
}

if (defined($ENV{"INSTPARQUE"})){
	$INSTPARQUE = $ENV{"INSTPARQUE"};
}else{
	$INSTPARQUE = "parque_instalado/";
}


$CLI_MAE = $MAEDIR."cli.mae";
$SUCU_MAE = $MAEDIR."sucu.mae";
$PROD_MAE = $MAEDIR."prod.mae";
$MOSTRAR_RESULTADO = 1;
$GRABAR_REPORTE = 1;
$SALIDA = $REPODIR.nombreReporte();
@TIPO_PRODUCTOS = ("INTERNETADSL", "INTERNETCABLEMODEM", "INTERNETDIALUP", "TVPORAIRE", "TVPORCABLE");
%REPORTE;

# separo las opciones si es que vienen agrupadas. por ej: -pis --> -p -s -i
@ARGV = separarOpciones();

# si se paso el parametro -h se muestra la ayuda y finaliza
if (existeOpcion("-h")){
	mostrarAyuda();
	exit 0;
}

# chequeo los parametros obligatorios: -p, -i, -s
if (!(existeOpcion("-p") && existeOpcion("-s") && existeOpcion("-i"))){
	print "No se ha pasado alguno de los parametros obligatorios. Lea la ayuda para la correcta ejecucion\n\n";
	mostrarAyuda();
	exit 0;
}

# seteo la forma de salida del reporte, por defecto se muestra por pantalla
# y se graba en un archivo
if (existeOpcion("-c") && existeOpcion("-e")){
	$MOSTRAR_RESULTADO = 1;
	$GRABAR_REPORTE = 1;
}else{
	if (existeOpcion("-c")){
	$MOSTRAR_RESULTADO = 1;
	$GRABAR_REPORTE = 0;
	}

	if (existeOpcion("-e")){
		$MOSTRAR_RESULTADO = 0;
		$GRABAR_REPORTE = 1;
	}
}

# chequeo que no se halla pasado algun parametro invalido
if (validarOpciones() == 0){
	mostrarAyuda();
	exit 1;
}

# limpio la pantalla si voy a mostrar el reporte por esta
if ($MOSTRAR_RESULTADO == 1){
	system("clear");
}

# obtengo los valores pasados a cada parametro
my @nombre_productos = obtenerNombreProductos();#"-p"
my @ids_sucursales = obtenerSucursales();#"-s"
my @ids_clientes = obtenerclientes();#"-i"
my $descripcion = obtenerDescripcion();#"-d"

my $texto;
# empiezo a procesar los archivos
($seg, $min, $hora, $dia, $mes, $anio, @zape) = localtime(time);
$mes++;
$anio+=1900;
$texto = "########################################################################
Reporte generado con comando ListarT ($hora:$min hs - $dia/$mes/$anio)
########################################################################

Comando de invocacion:\n\t \$> ListarT.pl ";

foreach $opt (@ARGV){
	$texto .= "$opt ";
}
$texto .= "\n\n\n";

imprimir($texto);
$total_instalado = 0;
#recorro cada archivo de productos a consultar para obtener las lineas que 
#matchean con la consulta
foreach $arch (@nombre_productos){
	open(ENTRADA, "<$INSTPARQUE$arch") || die "Error: No se pudo abrir parque_instalado/$arch\n";

	while (<ENTRADA>){
		chomp($_);
		#separo la linea leida por ","
		@linea = split(/,/, $_); 
		
		# hago la consulta
		if (matcheaConsulta(\@linea, \@ids_sucursales, \@ids_clientes, $descripcion)){
			reportarLinea(\@linea);
			$total_instalado++;
		}
	}
	close(ENTRADA);
	
	# imprimo el reporte
	imprimirReporte();
	
	# vacio el reporte por que cambio de tipo de producto
	vaciarReporte();
}

$texto = "\n\nCantidad total de productos instalados: $total_instalado\n\n";
imprimir($texto);

########################################################################
# Funciones
########################################################################

# funcion para comparar los ids de sucursales usada en el sort
sub cmp_sucursal{
	if ($a < $b){
		return -1;
	}elsif ($a > $b){
		return 1;
	}else{
		0
	}
}

# funcion para comparar los ids de clientes usada en el sort
sub cmp_sucursal_data{
	my %list1 = %{$a};
	my %list2 = %{$b};
	
	if ($list1{"cli_id"} < $list2{"cli_id"}){
		return -1;
	}elsif ($list1{"cli_id"} > $list2{"cli_id"}){
		return 1;
	}else{
		0
	}
}

# Recorre el hash %REPORTE en el que se guardan las lineas matcheadas por la consulta
# para cada tipo de producto y lo manda a imprimir
sub imprimirReporte{
	@sucu_id_list = keys(%REPORTE);
	$cant_sucu = @sucu_id_list;
	if ($cant_sucu > 0){
		my $texto1 = "";
		$cant_prod = 0;
		
		#ordeno de forma ascendente por id de sucursal
		@sucu_id_list = sort cmp_sucursal @sucu_id_list;
		
		foreach $sucu_id (@sucu_id_list){
			@sucu_list = @{$REPORTE{$sucu_id}};
			
			# ordeno de forma ascendente por id de cliente
			@sucu_list = sort cmp_sucursal_data @sucu_list;
			
			$sucu_name = obtenerBranchName($sucu_id);
			$texto1 .= "Sucursal: $sucu_id - $sucu_name\n";
			
			$cont = 1;
			$cont_total = 1;
			foreach $data (@sucu_list){
				%data_hash = %{$data};
				$cli_name = obtenerCustomerName($data_hash{"cli_id"});
				$texto1 .= "  $cont)  Cliente:      ".$data_hash{"cli_id"}." - $cli_name
      P. Comercial: ".$data_hash{"plan_comercial"}."
      Item:         ".$data_hash{"item"}."
";
				$cont++;
				$cant_prod++;
			}
			$texto1 .= "\n------------------------------------------------------------------------\n\n";
		}
		
		$texto1 = "########################################################################
Tipo de Producto: $arch
Cantidad de Sucursales listadas:  $cant_sucu
Cantidad de productos instalados: $cant_prod
########################################################################
$texto1";

		imprimir($texto1);
	}
}

# vacio el hash REPORTE, lo hago asi por que esto: %REPORTE = {} me lo vacia pero
# cuando lo imprimo me imprime algo feo :-(
sub vaciarReporte{
	@sucu_id_list = keys(%REPORTE);
	foreach $sucu_id (@sucu_id_list){
		delete($REPORTE{$sucu_id});
	}
}

# obtengo el nombre del reporte a generar, busco cual es el maximo numero 
# de archivo de reporte generado y le sumo uno
sub nombreReporte{

	if (opendir(DIR, $REPODIR)){
		# obtengo un array con los archivos y/o carpetas del directorio
		@flist = readdir(DIR);
		closedir(DIR);
	}

	$max = 0;
	foreach (@flist){
		chomp($_);
		if ($_ eq "." || $_ eq ".."){
			next;
		}
		
		($nombre, $sec) = split(/\./, $_);

		if ($sec > $max){
			$max = $sec;
		}
	}
	$max += 1;
	return "lpi.$max";
}

# dependiendo de los parametros con los que han ejecutado ListarT esta funcion
# imprime por pantalla y/o graba a un archivo el reporte
sub imprimir{
	$texto = $_[0];
	
	if ($MOSTRAR_RESULTADO){
		print "$texto";
	}
	
	if ($GRABAR_REPORTE){
		open(REPORTE, ">>$SALIDA") || die("no se pudo abrir $salida para grabar el reporte\n");
		
		print REPORTE "$texto";
		close(REPORTE);
	}
}

# agrego en el hash %REPORTE la linea que ha matcheado con la consulta
sub reportarLinea{
	# aca tengo que buscar los datos desde los archivos maestros del 
	# cliente y sucursal y mostrarlos
	my $sucu_id;
	my $sucu_name;
	my $cli_id;
	my $cli_name;
	my $plan_comercial;
	my $item;
	
	my $texto;
	
	($sucu_id, $cli_id, $plan_comercial, $item) = @{$_[0]};
	
	my %data;
	$data{"cli_id"} = $cli_id;
	$data{"plan_comercial"} = $plan_comercial;
	$data{"item"} = $item;
	
	if (exists($REPORTE{$sucu_id})){
		push(@{$REPORTE{"$sucu_id"}}, \%data);
	}else{
		my @list;
		push(@list, \%data);
		$REPORTE{$sucu_id} =  \@list;
	}
}

sub matcheaConsulta{
	
	my @linea = @{$_[0]};
	my @ids_sucursales = @{$_[1]};
	my @ids_clientes = @{$_[2]};
	my $desc = $_[3];
	
	$flag_sucu = 0;
	$flag_cli = 0;
	$flag_desc = 0;
	
	my $aux1 = @ids_sucursales;
	my $aux2 = @ids_clientes;
	my $aux3 = length($desc);
	
	if ($aux1 < 1 && $aux2 < 1 && $aux3 <1){
		# estan todos los parametros vacios, no matchea
		return 0;
	}else{
		if ($aux1 < 1){
			$flag_sucu = 1;
		}
		
		if ($aux2 < 1){
			$flag_cli = 1;
		}
		
		if ($aux3 < 1){
			$flag_desc = 1;
		}
	}
	
	# chequeo el id de la sucursal
	my $id_sucu = $linea[0];
	foreach $id (@ids_sucursales){
		if ($id_sucu == $id || $id == "*"){
			$flag_sucu = 1;
			last;
		}
	}
	
	# chequeo el id del cliente
	my $id_cli = $linea[1];
	foreach $id (@ids_clientes){
		if ($id_cli == $id || $id == "*"){
			$flag_cli = 1;
			last;
		}
	}
	
	my $descripcion = $linea[2];
	chomp($desc);
	chomp($descripcion);

	if ($descripcion =~ m/.*$desc.*/i){
		$flag_desc = 1;
	}
	
	return ($flag_sucu && $flag_cli && $flag_desc);
}

# leo el Branch_Name del archivo maestro de sucursales
sub obtenerBranchName{
	my $sucu_id = $_[0];
	
	open(FD_SUCU, "<$SUCU_MAE") || die "Error: No se pudo abrir $SUCU_MAE\n";
	while (<FD_SUCU>){
		chomp($_);
		@linea = split(/,/, $_); #separo la cadena

		if ("$linea[2]" == "$sucu_id"){
			close(FD_SUCU);
			return $linea[3];
		}
	}
	close(FD_SUCU);
	return "";
}

# leo el Customer_name del archivo maestro de clientes
sub obtenerCustomerName{
	my $cli_id = $_[0];
	
	open(FD_CLI, "<$CLI_MAE") || die "Error: No se pudo abrir $CLI_MAE\n";
	while (<FD_CLI>){
		chomp($_);
		@linea = split(/;/, $_); #separo la cadena
		
		if ("$linea[0]" == "$cli_id"){
			close(FD_CLI);
			return $linea[2];
		}
	}
	close(FD_CLI);
	return "";
}

# parseo los parametros que me pasaron para sacar los tipos de productos
# y los valido
sub obtenerNombreProductos{
	my @nombre_prods = obtenerParams("-p");

	$cant_prods = @nombre_prods;
	if ($cant_prods == 0 && existeOpcion("-p")){
		# solo se paso el parametro -p sin ningun valor, entonces se
		# realiza la busqueda sobre todos los tipos de productos
		return @TIPO_PRODUCTOS;
	}
	
	# valido que sean todos nombre validos
	foreach $prod (@nombre_prods){
		if (! array_tiene_valor_str(\@TIPO_PRODUCTOS, $prod)){
			print "Error: $prod no es un tipo de producto valido\n";
			exit 1;
		}
	}
	
	return @nombre_prods;
}

# parseo los parametros que me pasaron para sacar los ids de sucursales
# si hay algun rango los expando
sub obtenerSucursales{
	my @sucursales = obtenerParams("-s");
	my @aux;
	
	$cant_params = @sucursales;
	if ($cant_params == 0 && existeOpcion("-s")){
		# si solo se paso el parametro -s sin ningun valor se realiza 
		# la consulta sobre todas las sucursales
		push(@aux, "*");
		return $aux;
	}
	
	foreach $sucu (@sucursales){
		chomp($sucu);
		if ($sucu =~ /^[0-9]+\-[0-9]+$/){
			#print "SE PASO UN RANGO\n\n\n";
			($inicio, $fin) = split(/-/, $sucu);
			
			if ($fin < $inicio){
				print "Error: rango invalido\n";
				exit 1;
			}
			
			my $i;
			for ($i = $inicio; $i <= $fin; $i++){
				push(@aux, $i);
			}
		}else{
			# tiene que ser un numero
			if ($sucu =~ /^[0-9]+$/){
				push(@aux, $sucu);
			}else{
				print "Error: $sucu no es un id valido de sucursal\n";
				exit 1;
			}
		}
	}
	
	return @aux;
}

# parseo los parametros que me pasaron para sacar los ids de clientes
sub obtenerclientes{
	my @clientes = obtenerParams("-i");
	my @aux;
	
	$cant_cli = @clientes;
	if ($cant_cli == 0 && existeOpcion("-i")){
		push(@aux, "*");
		return @aux;
	}
	
	# valido que sean numericos los ids de los clientes
	foreach $cli (@clientes){
		if (! $cli =~ /^[0-9]+$/){
			print "Error: $cli no es un id valido de cliente\n";
			exit 1;
		}
	}
	
	return @clientes;
}

# parseo los parametros que me pasaron para sacar el string de la descripcion
sub obtenerDescripcion{
	my @desc = obtenerParams("-d");
	
	return $desc[0];
}

# chequeo si el array pasado como parametro tiene el valor como strig
sub array_tiene_valor_str{

	foreach $valor (@{$_[0]}){
		if ($valor eq $_[1]){
			return 1;
		}
	}
	return 0;
}

# chequeo si el array pasado como parametro tiene el valor como valor numerico
sub array_tiene_valor_num{
	foreach $valor (@{$_[0]}){
		if ($valor == $_[1]){
			return 1;
		}
	}
	return 0;
}

# separo los parametros que ingresaron "unidos", por ejemplo: -psi lo paso a
# 3 parametros distintos: -p -s -i
sub separarOpciones{
	my @aux;
	my @aux2;
	
	foreach $opt (@ARGV){
		if ($opt =~ /^\-[psidceh]{2,}$/){
			@aux2 = split(//, $opt);
			foreach $opt2 (@aux2){
				if ($opt2 ne "-"){
					push(@aux, "-".$opt2);
				}
			}
		}else{
			push(@aux, $opt);
		}
	}

	return @aux;
}

# valido que las opciones que me pasaron sean validas
sub validarOpciones{
	foreach $opt (@ARGV){
		if ($opt =~ /^\-/){
			if (esOpcionValida($opt) == 0){
				return 0;
			}
		}
	}
	
	return 1;
}

# chequea si un parametro de la forma -[a-zA-Z] sea una opcion valida
sub esOpcionValida{
	if ($_[0] =~ /^\-[psidceh]{1}$/){
		return 1;
	}else{
		return 0;
	}
}

# imprime la ayuda del comando por pantalla
sub mostrarAyuda{
	print "Ayuda del comando ListarT

Este comando resulve consultas efectuadas sobre el parque instalado y 
emite informes correspondiente cuando se lo requiera.

Modo de empleo:
	ListarT.sh [OPCIONES]
	
Las opciones validas son:
    -p  Tipo de productos a listar, debe ser algun tipo de producto 
        valido. Permite un valor, varios separados por espacios o todos 
        si no se le pasa ningun valor. Este parametro es obligatorio.
		
    -s  Sucursal o sucursales que se van a listar. Permite un valor, 
        varios valores separados por espacios o un rango de ellos por 
        ejemplo:
            ListarT.sh -s 100-105 106 108
           
        o todas las sucursales si no se lle pasa ningun valor. Este 
        parametro es obligatorio.
			
    -i  Cliente o clientes que se van a listar. Permite un valor, varios
        separados por espacios o todos los clientes si no se le pasa 
        ningun valor. Este parametro es obligatorio.
	
    -d  Cadena de texto que se buscara en la Descripcion del item de 
        Producto del registro cabecera, este matcheara de forma completa
        o una subcadena de este. Este parametro es opcional.
		
    -c  Resuelve la consulta y muestra los resultados sin grabar el 
        reporte en un archivo. Este parametro es opcional.
		
    -e  Resuelve la consulta y graba el reporte en una archivo. Este 
        parametro es opcional.
	
    -h  Muestra a ayuda del comando.\n\n";
}

# verifico si me han pasado por parametro al comando ListarT la opcion buscada
sub existeOpcion{
	foreach $opt (@ARGV){
		if ($opt eq $_[0]){
			return 1;
		}
	}
	return 0;
}

# obtengo los valores pasados a algun parametro, por ejemplo si se ejecuta
# con -s 102 103 108 me retorna un array con los valores (102,103,108)
sub obtenerParams{
	my @params;
	my $save = 0;
	foreach $opt (@ARGV){
		chomp($opt);
		if ($opt eq $_[0]){
			$save = 1;
			next;
		}
		
		# si llegue al proximo flag de parametro salgo
		if ($opt =~ /^\-[psidceh]{1}$/ && $save == 1){
			last;
		}
		
		if ($save == 1){
			push(@params, $opt);
			
		}
	}
	
	return @params;
}


